﻿using System.Windows;
using System.Windows.Controls;
using System.Collections.Generic;
using SuperGo.Silverlight.WebApp;
using System;
using System.Windows.Media;
using System.ComponentModel;

namespace SuperGo.Silverlight {
	public partial class InitiateGame {
		public enum InitiateGameStates {
			InitialRequest,
			ViewRequest,
			CounterRequest
		}

		public class ViewGame : INotifyPropertyChanged {
			public ViewGame(WsGame game, bool isEnabled) {
				Game = game;
				IsEnabled = isEnabled;

				BoardSize9 = game.BoardSize == 9;
				BoardSize13 = game.BoardSize == 13;
				BoardSize19 = game.BoardSize == 19;
				IPlayBlack = !game.OpponentIsBlack;
				TheyPlayBlack = game.OpponentIsBlack;
				Komi = game.Komi.ToString("0.0");
			}

			private bool _isEnabled;
			
			public bool IsEnabled {
				get { return _isEnabled; }
				set {
					_isEnabled = value;
					if (PropertyChanged != null) {
						PropertyChanged(this, new PropertyChangedEventArgs("IsEnabled"));
						PropertyChanged(this, new PropertyChangedEventArgs("Foreground"));
						PropertyChanged(this, new PropertyChangedEventArgs("ReadOnly"));
					}
				} 
			}

			public bool BoardSize9 { get; set; }
			public bool BoardSize13 { get; set; }
			public bool BoardSize19 { get; set; }
			public bool IPlayBlack { get; set; }
			public bool TheyPlayBlack { get; set; }
			public string Komi { get; set; }
			public WsGame Game { get; set; }
			public bool ReadOnly { get { return !IsEnabled; } }
			public Brush Foreground {
				get {
					return IsEnabled ? 
						new SolidColorBrush(Colors.Black) : 
						new SolidColorBrush(Colors.Gray);
				}
			}

			public event PropertyChangedEventHandler PropertyChanged;
		}

		private InitiateGameStates _state;
		private readonly string[] _handicaps = new[] { "0", "2", "3", "4", "5", "6", "7", "8", "9" };
		private ViewGame _viewGame = null;

		public InitiateGameStates State {
			get { return _state; }
			set {
				_state = value;
				SetControlsVisibility(value);
			}
		}

		private readonly WsGame _defaultGame = new WsGame {
			BoardSize = 9,
			BlackHandicap = 0,
			DateRequestAccepted = null,
			Komi = 5.5M,
			Opponent = null,
			OpponentIsBlack = false,
			Rated = true
		};

		private void SetControlsVisibility(InitiateGameStates state) {
			bool playerIsViewingTheirOwnRequest = _viewGame.Game.RequestInitiatedByBlack != _viewGame.Game.OpponentIsBlack;

			_buttonPanel.SetVisible(_withdraw, state == InitiateGameStates.ViewRequest && playerIsViewingTheirOwnRequest);
			_buttonPanel.SetVisible(_accept, state == InitiateGameStates.ViewRequest && !playerIsViewingTheirOwnRequest);
			_buttonPanel.SetVisible(_reject, state == InitiateGameStates.ViewRequest && !playerIsViewingTheirOwnRequest);
			_buttonPanel.SetVisible(_counter, state == InitiateGameStates.ViewRequest && !playerIsViewingTheirOwnRequest);
			_buttonPanel.SetVisible(_sendRequest, state == InitiateGameStates.InitialRequest || state == InitiateGameStates.CounterRequest);
			_buttonPanel.SetVisible(_cancel, true);
			_viewGame.IsEnabled = state == InitiateGameStates.InitialRequest || state == InitiateGameStates.CounterRequest;
			_beginAGamePanel.DataContext = _viewGame;
		}

		public InitiateGame() {
			try {
				InitializeComponent();

				this.Loaded += new RoutedEventHandler(InitiateGame_Loaded);
			} catch (Exception ex) {
				HandleException(ex);
			}
		}

		public void SetFriendsList(IEnumerable<WsPlayer> allFriends) {
			_friendsList.AllFriends = allFriends;
		}

		void InitiateGame_Loaded(object sender, RoutedEventArgs e) {
			_buttonPanel = (ButtonPanel)_beginAGamePanel.FindName("_buttonPanel");
			_boardSize9 = (RadioButton)_beginAGamePanel.FindName("_boardSize9");
			_boardSize13 = (RadioButton)_beginAGamePanel.FindName("_boardSize13");
			_boardSize19 = (RadioButton)_beginAGamePanel.FindName("_boardSize19");
			_iPlayBlack = (RadioButton)_beginAGamePanel.FindName("_iPlayBlack");
			_theyPlayBlack = (RadioButton)_beginAGamePanel.FindName("_theyPlayBlack");
			_friendsList = (FriendsList)_beginAGamePanel.FindName("_friendsList");
			_handicap = (ComboBox)_beginAGamePanel.FindName("_handicap");
			_komi = (TextBox)_beginAGamePanel.FindName("_komi");
			_errorMessage = (TextBlock)_beginAGamePanel.FindName("_errorMessage");

			_sendRequest = (Button)_buttonPanel.FindName("_sendRequest");
			_accept = (Button)_buttonPanel.FindName("_accept");
			_reject = (Button)_buttonPanel.FindName("_reject");
			_cancel = (Button)_buttonPanel.FindName("_cancel");
			_counter = (Button)_buttonPanel.FindName("_counter");
			_withdraw = (Button)_buttonPanel.FindName("_withdraw");

			_accept.Click += new RoutedEventHandler(Accept_Click);
			_reject.Click += new RoutedEventHandler(Reject_Click);
			_counter.Click += new RoutedEventHandler(Counter_Click);
			_sendRequest.Click += new RoutedEventHandler(Start_Click);
			_cancel.Click += new RoutedEventHandler(Cancel_Click);
			_withdraw.Click += new RoutedEventHandler(Withdraw_Click);
			_boardSize9.Checked += new RoutedEventHandler(BoardSize9_Checked);
			_boardSize13.Checked += new RoutedEventHandler(BoardSize13_Checked);
			_boardSize19.Checked += new RoutedEventHandler(BoardSize19_Checked);

			_handicap.Items = _handicaps;
			_handicap.SelectedItem = _handicaps[0];
		}

		void Withdraw_Click(object sender, RoutedEventArgs e) {
			Page.WithdrawRequest(_viewGame.Game);
		}

		void Reject_Click(object sender, RoutedEventArgs e) {
			Page.RejectGame(_viewGame.Game);
		}

		void Accept_Click(object sender, RoutedEventArgs e) {
			Page.AcceptGame(_viewGame.Game);
		}

		void Cancel_Click(object sender, RoutedEventArgs e) {
			if (State == InitiateGameStates.CounterRequest) {
				State = InitiateGameStates.ViewRequest;
			} else {
				Page.ShowContinueExistingGame();
			}
		}

		void Counter_Click(object sender, RoutedEventArgs e) {
			State = InitiateGameStates.CounterRequest;
		}

		public override void Show() {
			RequireIgsAccount();
			_viewGame = new ViewGame(_defaultGame, true);
			SetControlValues(_viewGame);
			State = InitiateGameStates.InitialRequest;
			base.Show();
		}

		private void RequireIgsAccount() {
			if (String.IsNullOrEmpty(Page.CurrentPlayer.IgsUsername)) {
				const string message = "Sorry, you cannot create a game without first specifying an Internet Go Server (IGS) Account.  Super Go uses IGS to track your rank.  Would you like to specify your IGS account information now?";
				Page.ShowDialog("IGS Account Required", message, MessageBoxButtons.YesNo, RequireIgsAccount_Closed);
				// goto RequireIgsAccount_Closed
			}
		}

		private void RequireIgsAccount_Closed(DialogResult result) {
			if (result == DialogResult.Yes) {
				Page.ShowPreferences();
			} else {
				Page.ShowGamePage();
			}
		}

		public void Show(WsGame wsGame) {
			try {
				_viewGame = new ViewGame(wsGame, false);
				SetControlValues(_viewGame);
				State = InitiateGameStates.ViewRequest;
				base.Show();
			} catch (Exception ex) {
				HandleException(ex);
			}
		}

		private void SetControlValues(ViewGame viewGame) {
			WsGame wsGame = viewGame.Game;

			_beginAGamePanel.DataContext = viewGame;
			
			_friendsList.SetSelectedItem(wsGame.Opponent);
			_handicap.SelectedItem = wsGame.BlackHandicap.ToString();
		}

		void BoardSize19_Checked(object sender, RoutedEventArgs e) {
			Page.DrawBoard(19);
		}

		void BoardSize13_Checked(object sender, RoutedEventArgs e) {
			Page.DrawBoard(13);
		}

		void BoardSize9_Checked(object sender, RoutedEventArgs e) {
			Page.DrawBoard(9);
		}

		void Start_Click(object sender, RoutedEventArgs e) {
			try {
				if (!IsFormValid())
					return;
				
				WsPlayer opponent = _friendsList.GetSelectedItem();

				WsGame newGame = new WsGame {
					GameId = _viewGame.Game.GameId,
					BoardSize = GetBoardSize(),
					Opponent = opponent,
					OpponentIsBlack = (_theyPlayBlack.IsChecked == true),
					BlackHandicap = Convert.ToInt32(_handicap. SelectedItem),
					Komi = Convert.ToDecimal(_komi.Text),
					RequestInitiatedByBlack = !(_theyPlayBlack.IsChecked == true)
				};

				if (_state == InitiateGameStates.InitialRequest)
					Page.StartGame(newGame);
				else if (State == InitiateGameStates.CounterRequest)
					Page.CounterGame(newGame);
			} catch (Exception ex) {
				HandleException(ex);
			}
		}

		private bool IsFormValid() {
			string errorMessage = null;

			if (_friendsList.GetSelectedItem() == null)
				errorMessage = "Please select an opponent.";
			int handicap;
			if (!Int32.TryParse(_handicap.SelectedItem.ToString(), out handicap))
				errorMessage = "Please select a valid handicap.";
			if (handicap < 0 || handicap > 9)
				errorMessage = "Please select a handicap between 0 and 9.";
			if (handicap == 1)
				errorMessage = "1 is not a valid handicap because that is equivalent to black playing first.";
			double komi;
			if (!Double.TryParse(_komi.Text, out komi))
				errorMessage = "Komi must be a number.";
			if (komi < 0)
				errorMessage = "Komi must be greater than 0";
			if (komi > 50)
				errorMessage = "Komi must be less than 50";
			if (String.IsNullOrEmpty(_komi.Text))
				errorMessage = "Please enter a komi";

			bool errorFound = errorMessage != null;
			if (errorFound) {
				_errorMessage.Text = errorMessage;
				_errorMessage.Visibility = Visibility.Visible;
			}
			return !errorFound;
		}

		private int GetBoardSize() {
			int boardSize = 9;

			if (_boardSize19.IsChecked == true)
				boardSize = 19;
			if (_boardSize13.IsChecked == true)
				boardSize = 13;
			return boardSize;
		}
	}
}
